#include "bsp_usart.h"
#include "stdint.h"
// 定义串口pipe
uint8_t usart1_recv_buf[USART1_BUFF_SIZE];
Pipe_t usart1_pipe = {usart1_recv_buf, USART1_BUFF_SIZE, 0, 0, false};

uint8_t usart2_recv_buf[USART2_BUFF_SIZE];
Pipe_t usart2_pipe = {usart2_recv_buf, USART2_BUFF_SIZE, 0, 0, false};

uint8_t usart3_recv_buf[USART3_BUFF_SIZE];
Pipe_t usart3_pipe = {usart3_recv_buf, USART3_BUFF_SIZE, 0, 0, false};

uint8_t lpUart_recv_buf[LPUART_BUFF_SIZE];
Pipe_t lpUart_pipe = {lpUart_recv_buf, LPUART_BUFF_SIZE, 0, 0, false};

//初始化函数，由stm32mx生成
void MX_USART1_UART_Init(void) {
    LL_USART_InitTypeDef USART_InitStruct = {0};

    LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

    LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2);

    NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 2, 0));
    NVIC_EnableIRQ(USART1_IRQn);
    /* Peripheral clock enable */
    LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1);

    LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
    /**USART1 GPIO Configuration
    PA9   ------> USART1_TX
    PA10   ------> USART1_RX
    */
    GPIO_InitStruct.Pin = LL_GPIO_PIN_9 | LL_GPIO_PIN_10;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
    GPIO_InitStruct.Alternate = LL_GPIO_AF_7;
    LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    USART_InitStruct.BaudRate = 115200;
    USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
    USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
    USART_InitStruct.Parity = LL_USART_PARITY_NONE;
    USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
    USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
    USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
    LL_USART_DisableOverrunDetect(USART1);   //关闭ORE 检测 防止检测到overrun
    LL_USART_Init(USART1, &USART_InitStruct);
    LL_USART_ConfigAsyncMode(USART1);
    LL_USART_EnableIT_RXNE(USART1);    //使能RXNE中断
    LL_USART_EnableIT_IDLE(USART1);    //使能串口空闲中断
    LL_USART_Enable(USART1);                //使能SUART1

}
//串口2初始化
void MX_USART2_UART_Init(void) {
    LL_USART_InitTypeDef USART_InitStruct = {0};
    LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
    LL_RCC_SetUSARTClockSource(LL_RCC_USART2_CLKSOURCE_PCLK1);
    /* Peripheral clock enable */
    LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART2);

    LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
    /**USART2 GPIO Configuration
    PA2   ------> USART2_TX
    PA3   ------> USART2_RX
    */
    GPIO_InitStruct.Pin = LL_GPIO_PIN_2 | LL_GPIO_PIN_3;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
    GPIO_InitStruct.Alternate = LL_GPIO_AF_7;
    LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    //  LL_GPIO_SetPinPull(GPIOA,LL_GPIO_PIN_3,LL_GPIO_PULL_UP);//设置上拉输入模式
    NVIC_SetPriority(USART2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
    NVIC_EnableIRQ(USART2_IRQn);
    USART_InitStruct.BaudRate = 9600;
    USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
    USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
    USART_InitStruct.Parity = LL_USART_PARITY_NONE;
    USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
    USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
    USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
    LL_USART_Init(USART2, &USART_InitStruct);
    LL_USART_DisableOverrunDetect(USART2);   //关闭ORE 检测 防止检测到overrun
    LL_USART_ConfigAsyncMode(USART2);
    LL_USART_EnableIT_IDLE(USART2);//使能串口空闲中断
    LL_USART_EnableIT_RXNE(USART2);
    LL_USART_Enable(USART2);
}

void MX_USART3_UART_Init(void) {

    /* USER CODE BEGIN USART3_Init 0 */

    /* USER CODE END USART3_Init 0 */

    LL_USART_InitTypeDef USART_InitStruct = {0};

    LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

    LL_RCC_SetUSARTClockSource(LL_RCC_USART3_CLKSOURCE_PCLK1);

    /* Peripheral clock enable */
    LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART3);

    LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
    /**USART3 GPIO Configuration
    PC4   ------> USART3_TX
    PC5   ------> USART3_RX
    */
    GPIO_InitStruct.Pin = LL_GPIO_PIN_4 | LL_GPIO_PIN_5;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
    GPIO_InitStruct.Alternate = LL_GPIO_AF_7;
    LL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    /* USART3 interrupt Init */
    NVIC_SetPriority(USART3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 1));
    NVIC_EnableIRQ(USART3_IRQn);

    /* USER CODE BEGIN USART3_Init 1 */

    /* USER CODE END USART3_Init 1 */
    USART_InitStruct.BaudRate = 115200;
    USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
    USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
    USART_InitStruct.Parity = LL_USART_PARITY_NONE;
    USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
    USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
    USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
    LL_USART_Init(USART3, &USART_InitStruct);
    LL_USART_DisableOverrunDetect(USART3);   //关闭ORE 检测 防止检测到overrun

    LL_USART_ConfigAsyncMode(USART3);
    LL_USART_EnableIT_IDLE(USART3);//使能串口空闲中断
    LL_USART_EnableIT_RXNE(USART3);
    LL_USART_Enable(USART3);

    /* USER CODE BEGIN USART3_Init 2 */

    /* USER CODE END USART3_Init 2 */

}

void MX_LPUART1_UART_Init(void) {
    LL_LPUART_InitTypeDef LPUART_InitStruct = {0};
    LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
    LL_RCC_SetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_SYSCLK);  //选择LSE 时钟，保持在睡眠模式时钟仍正常工作
    /* Peripheral clock enable */
    LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LPUART1);
    LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
    /**LPUART1 GPIO Configuration
    PC0   ------> LPUART1_RX
    PC1   ------> LPUART1_TX
    */
    GPIO_InitStruct.Pin = LL_GPIO_PIN_0 | LL_GPIO_PIN_1;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
    GPIO_InitStruct.Alternate = LL_GPIO_AF_8;
    LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    /* LPUART1 interrupt Init */
    NVIC_SetPriority(LPUART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
    NVIC_EnableIRQ(LPUART1_IRQn);
    LPUART_InitStruct.BaudRate = 115200;
    LPUART_InitStruct.DataWidth = LL_LPUART_DATAWIDTH_8B;
    LPUART_InitStruct.StopBits = LL_LPUART_STOPBITS_1;
    LPUART_InitStruct.Parity = LL_LPUART_PARITY_NONE;
    LPUART_InitStruct.TransferDirection = LL_LPUART_DIRECTION_TX_RX;
    LPUART_InitStruct.HardwareFlowControl = LL_LPUART_HWCONTROL_NONE;
    LL_LPUART_Init(LPUART1, &LPUART_InitStruct);

    LL_LPUART_ClearFlag_IDLE(LPUART1);//清除IDLE标志位


    LL_USART_DisableOverrunDetect(LPUART1);   //关闭ORE 检测 防止检测到overrun
    LL_LPUART_SetWKUPType(LPUART1, LL_LPUART_WAKEUP_ON_RXNE); //设置RXNE接收唤醒
    LL_LPUART_ClearFlag_WKUP(LPUART1);
    LL_LPUART_EnableIT_RXNE(LPUART1);               //使能RXNE中断
    //  LL_LPUART_EnableIT_IDLE(LPUART1);
    LL_LPUART_EnableInStopMode(LPUART1);    //低功耗模式下仍然启用
    LL_USART_Enable(LPUART1);               //使能SUART1
}


void Usart1_init(void) {
    MX_USART1_UART_Init();
}
void Usart2_init(void) {
    MX_USART2_UART_Init();
}
void Usart3_init(void) {
    MX_USART3_UART_Init();
}
void LPUART_init(void) { //低功耗串口初始化
    MX_LPUART1_UART_Init();
}

static void usart1_Send(char* info, uint16_t len) {
    uint16_t i;
    for (i = 0; i < len; i++) {
        while (RESET == LL_USART_IsActiveFlag_TXE(USART1))
            ;
        LL_USART_TransmitData8(USART1, info[i]);
    }
}
static void usart2_Send(char* info, uint16_t len) {
    uint16_t i;
    for (i = 0; i < len; i++) {
        while (RESET == LL_USART_IsActiveFlag_TXE(USART2))
            ;
        LL_USART_TransmitData8(USART2, info[i]);
    }
}
static void usart3_Send(char* info, uint16_t len) {
    uint16_t i;
    for (i = 0; i < len; i++) {
        while (RESET == LL_USART_IsActiveFlag_TXE(USART3))
            ;
        LL_USART_TransmitData8(USART3, info[i]);
    }
}
static void lpUart_Send(char* info, uint16_t len) { //低功耗串口发送函数
    uint16_t i;
    for (i = 0; i < len; i++) {
        while (RESET == LL_LPUART_IsActiveFlag_TXE(LPUART1))
            ;
        //    LL_USART_TransmitData8(LPUART1, info[i]);
        LL_LPUART_TransmitData8(LPUART1, info[i]);
    }
}


// pipe块写入
bool Pipe_block_input(Pipe_t* Pipe, const uint8_t* packet, uint16_t packetlen) {
    if (Pipe == NULL || packet == NULL || packetlen == 0) {
        return false;
    }
    if (Pipe->sum + packetlen > Pipe->size) {
        return false;
    }
    if (Pipe->pin + packetlen <= Pipe->size) { // 判断是否有空余空间存储
        memcpy((void*)&Pipe->buf[Pipe->pin], (const void*)packet, packetlen);
    } else {
        // 从头开始覆写
        memcpy((void*)&Pipe->buf[Pipe->pin], (const void*)packet, (Pipe->size - Pipe->pin));
        memcpy((void*)&Pipe->buf[0], (const void*)(packet + (Pipe->size - Pipe->pin)), packetlen - (Pipe->size - Pipe->pin));
    }
    // 更新pin 和 sum
    Pipe->pin += packetlen;
    Pipe->pin %= Pipe->size;
    Pipe->sum += packetlen;
    return true;
}

// 移除前面pipe前len个数据
void pipe_remove(Pipe_t* pipe, uint16_t len) {
    if (pipe == NULL || pipe->sum < len || len == 0 || len > pipe->size) {
        return;
    }
    pipe->sum -= len;
    memmove((void*)pipe->buf, (const void*)(pipe->buf + len), pipe->sum);   // 直接把后面的数据往前面移动
    pipe->pin = pipe->sum;
    pipe->flag = false;
}
// 复位pipe
void pipe_reset(Pipe_t* pipe) {
    // 不需要清除数据，只要把有效数据的标志位复位就可以了
    if (pipe == NULL) {
        return;
    }
    pipe->pin = 0;
    pipe->sum = 0;
    pipe->flag = false;
}
//链接串口pipe和handle
void Usart_Link_Config(Port_com port_com, USUART_Handler_t* Port) {
    switch (port_com) {
        case PORT1_COM:
            Port->pipe = &usart1_pipe;
            Port->Send = usart1_Send;
            break;
        case PORT2_COM:
            Port->pipe = &usart2_pipe;
            Port->Send = usart2_Send;
            break;
        case PORT3_COM:
            Port->pipe = &usart3_pipe;
            Port->Send = usart3_Send;
            break;
        case LPUART_COM:
            Port->pipe = &lpUart_pipe;
            Port->Send = lpUart_Send;
        default:
            break;
    }
    Port->pipe_remove = pipe_remove;
    Port->pipe_reset = pipe_reset;
}


void USART1_IRQHandler(void) {
    char data;
    if (LL_USART_IsActiveFlag_RXNE(USART1) && LL_USART_IsEnabledIT_RXNE(USART1)) {
        data = LL_USART_ReceiveData8(USART1);
        Pipe_block_input(&usart1_pipe, (const uint8_t*)&data, 1);
    }
    if (LL_USART_IsActiveFlag_IDLE(USART1)) { // 串口接收空闲中断
        LL_USART_ClearFlag_IDLE(USART1);
        LL_USART_ReceiveData8(USART1);
        usart1_pipe.flag = true; // 接收到完整的数据包
    }
}
void USART2_IRQHandler(void) {
    char data;
    if (LL_USART_IsActiveFlag_RXNE(USART2) == SET) { // 串口接收中断
        data = LL_USART_ReceiveData8(USART2);
        Pipe_block_input(&usart2_pipe, (const uint8_t*)&data, 1);
    }
    if (LL_USART_IsActiveFlag_IDLE(USART2)) { // 串口接收空闲中断
        LL_USART_ClearFlag_IDLE(USART2);
        LL_USART_ReceiveData8(USART2);
        usart2_pipe.flag = true; // 接收到完整的数据包
    }
}

void USART3_IRQHandler(void) {
    char data;
    if (LL_USART_IsActiveFlag_RXNE(USART3) == SET) { // 串口接收中断
        data = LL_USART_ReceiveData8(USART3);  //M4内核读数据会自动清除RXNE
        Pipe_block_input(&usart3_pipe, (const uint8_t*)&data, 1);
    }
    if (LL_USART_IsActiveFlag_IDLE(USART3)) { // 串口接收空闲中断
        LL_USART_ClearFlag_IDLE(USART3);
        usart3_pipe.flag = true; // 接收到完整的数据包
    }
}



void LPUART1_IRQHandler(void) {
    char data;
    if (LL_LPUART_IsActiveFlag_RXNE(LPUART1) == SET) {
        data = LL_LPUART_ReceiveData8(LPUART1);
        Pipe_block_input(&lpUart_pipe, (const uint8_t*)&data, 1);
        lpUart_pipe.flag = true;
    }
}

//串口重定向函数
int fputc(int ch, FILE *f) {
    LL_USART_TransmitData8(USART1, ch);
    while (!LL_USART_IsActiveFlag_TXE(USART1)); //需要等待发送完成
    return ch;
}